<template>
  <scroll-view
    scroll-x
    scroll-with-animation
    :scroll-left="scrollDist"
    :class="['tabs', tabs.length <= 5 && 'non-scrollable']"
  >
    <view class="scroll-bar" v-if="tabs.length">
      <view
        v-for="(tab, index) in tabs"
        :key="tab.id"
        :class="['tab-item', modelValue === index && 'active']"
        @click="onToggleTab(tab, index)"
        >{{ tab.name }}</view
      >
      <view
        class="slide-line"
        :style="{
          transform: `translateX(${scrollLine}px) translateX(${
            scrollLine ? '-50%' : '-100%'
          })`
        }"
      ></view>
    </view>
  </scroll-view>
</template>

<script setup>
import { ref, watch, onMounted, getCurrentInstance, nextTick } from 'vue'

const props = defineProps({
  tabs: {
    type: Array,
    default: () => []
  },
  modelValue: {
    type: Number,
    default: 0
  }
})

const emit = defineEmits(['update:modelValue', 'change'])

const scrollDist = ref(0)
const scrollLine = ref(0)
const componentInstance = getCurrentInstance()
let tabsRect = {}
let tabItemsRect = []

onMounted(() => {
  querySelectorRect()
})

watch(
  () => props.tabs,
  () => {
    querySelectorRect()
  }
)

watch(
  () => props.modelValue,
  value => {
    calcScrollDist(value)
  }
)

/**
 * 标签切换
 */
function onToggleTab(tab, index) {
  if (props.modelValue !== index) {
    emit('update:modelValue', index)
    emit('change', tab)
  }
}

function querySelectorRect() {
  uni
    .createSelectorQuery()
    .in(componentInstance)
    .select('.tabs')
    .boundingClientRect()
    .selectAll('.tab-item')
    .boundingClientRect()
    .exec(([tabs, tabItems]) => {
      tabsRect = tabs
      tabItemsRect = tabItems
      calcScrollDist(props.modelValue)
    })
}

/**
 * 计算滚动距离
 */
function calcScrollDist(current) {
  const tabsWidth = tabsRect.width
  if (!tabItemsRect.length) return void 0
  const currentTabWidth = tabItemsRect[current].width
  let offsetLeft = 0
  for (let i = 0; i < current; ++i) {
    const tabItemWidth = tabItemsRect[i].width
    offsetLeft += tabItemWidth
  }
  scrollDist.value = offsetLeft - (tabsWidth - currentTabWidth) / 2
  scrollLine.value = offsetLeft + currentTabWidth / 2
}
</script>

<style scoped lang="scss">
.tabs {
  height: 88rpx;
  white-space: nowrap;
  background-color: #fff;
  ::-webkit-scrollbar {
    display: none;
  }
  .scroll-bar {
    height: 100%;
    display: inline-flex;
    position: relative;
    .tab-item {
      height: 100%;
      padding-left: 32rpx;
      padding-right: 32rpx;
      font-size: 34rpx;
      color: #333;
      display: flex;
      align-items: center;
      justify-content: center;
      &.active {
        color: #4771f6;
        font-weight: bold;
      }
    }
  }
}
.tabs.non-scrollable {
  .scroll-bar {
    display: flex;
    .tab-item {
      flex: 1;
    }
  }
}
.slide-line {
  width: 66rpx;
  height: 8rpx;
  border-radius: 4rpx;
  background-color: #4771f6;
  transition: transform 0.3s;
  position: absolute;
  bottom: 0;
}
</style>
